package cn.nr19.jian

import cn.nr19.jian.exception.BreakException
import cn.nr19.jian.exception.ParserException
import cn.nr19.jian.exception.ReturnException
import cn.nr19.jian.exception.TokenException
import cn.nr19.jian.factory.JsFactory
import cn.nr19.jian.factory.NodeFactory
import cn.nr19.jian.factory.TokenFactory

import cn.nr19.jian.`object`.JianLei
import cn.nr19.jian.`object`.JianLei2
import cn.nr19.jian.`object`.JianLeiApi
import cn.nr19.jian.`object`.ARR
import cn.nr19.jian.`object`.EON
import cn.nr19.jian.`object`.JianObject
import cn.nr19.jian.`object`.JianViewObject
import cn.nr19.jian.`object`.function.JianSystemFunctionObject
import cn.nr19.jian.token.ARRNode
import cn.nr19.jian.token.BooleanNode
import cn.nr19.jian.token.BreakNode
import cn.nr19.jian.token.ContinueNode
import cn.nr19.jian.token.E2Node
import cn.nr19.jian.token.ENode
import cn.nr19.jian.token.EONJNode
import cn.nr19.jian.token.EONNode
import cn.nr19.jian.token.ForNode
import cn.nr19.jian.token.FuzhiNode
import cn.nr19.jian.token.GFunNode
import cn.nr19.jian.token.IFNode
import cn.nr19.jian.token.IFX
import cn.nr19.jian.token.IFXIS
import cn.nr19.jian.token.IFXOR
import cn.nr19.jian.token.IMPORT
import cn.nr19.jian.token.J2Node
import cn.nr19.jian.token.LAYOUT
import cn.nr19.jian.token.NEventNode
import cn.nr19.jian.token.NFunNode
import cn.nr19.jian.token.NULL
import cn.nr19.jian.token.NumNode
import cn.nr19.jian.token.NVarNode
import cn.nr19.jian.token.Node
import cn.nr19.jian.token.Obj1Node
import cn.nr19.jian.token.Obj2Node
import cn.nr19.jian.token.ReturnNode
import cn.nr19.jian.token.StrNode
import cn.nr19.jian.token.SuanNode
import cn.nr19.jian.token.Token
import cn.nr19.jian.token.VarNode
import cn.nr19.jian.token.VARSELF
import cn.nr19.jian.token.WhenNode
import cn.nr19.jian.token.E3Node
import cn.nr19.jian.token.ENodes
import cn.nr19.jian.token.InNode
import cn.nr19.jian.token.JsNode
import cn.nr19.jian.token.LayoutNode
import cn.nr19.jian.token.NotesNode
import cn.nr19.jian.token.ParNode
import cn.nr19.jian.token.SymbolNode
import java.lang.IndexOutOfBoundsException
import java.util.regex.Pattern

object Jian {

    // 系统功能集
    private var f_def : JianSystemFunctionObject?= null
    fun init(def : JianSystemFunctionObject){
        this.f_def = def
    }
    fun def() : JianSystemFunctionObject {
        return f_def ?: createDefFunction()
    }

    private fun createDefFunction() : JianSystemFunctionObject {
        f_def = JianSystemFunctionObject()
        return f_def!!
    }

    /**
     * 解析类，从代码开始解析，需要先读取 token 再实现边读边解析。
     * @param code  简代码
     * @return 解析完成返回简类
     */
    fun p(code : String, lei : JianLeiApi = JianLei(), errorListener: OnJianParserListener ?= null) : Any{
        try {
            if (errorListener != null){
                lei.setConf("parser_listener",errorListener)
                lei.setConf("code",code)
            }
            J2Node().let {
                it.nodes.addAll(NodeFactory.start(TokenFactory().start(code)))
                return p(it,lei)
            }
        }catch (e : TokenException){
            e.printStackTrace()
            lei.getParserListener()?.onLangError(errMsg(code,(Str(lei.getConf("TAG")) ?:"") + "." + (e.message?:""),e.position))
           J2Utils.log(errMsg(code,(Str(lei.getConf("TAG")) ?:"") + "." + (e.message?:""),e.position))
            return "失败a ${e}"
        }catch (e : ParserException){
            e.printStackTrace()

            lei.getParserListener()?.onParserError(errMsg(code,(Str(lei.getConf("TAG")) ?:"")  + "." + (e.message?:""),e.position))
            J2Utils.log("err code",code)
            return "失败b ${e}"
        }

        catch (e : Exception){
            e.printStackTrace()
            errorListener?.onParserError(e.toString())

            return "失败c${e}"
        }
    }

    /**
     * 解析视图
     * @param code 必须纯布局代码
     * @param 是否为布局编辑器编辑
     */
    fun pView(code : String, lei : JianLeiApi,errorListener: OnJianParserListener ?= null,isLayoutEditorParser : Boolean = false) : JianViewObject?{
        try {
            NodeFactory().startLayout(code,0).let { lt ->
                return if (isLayoutEditorParser) pLayout2Edit(lt,lei)
                else pLayout(lt,lei)
            }

        }catch (e : TokenException){
            e.printStackTrace()
            errorListener?.onLangError(errMsg(Str(lei.getConf("code")),e.message?:"",e.position))

            return null
        }catch (e : ParserException){
            e.printStackTrace()
            J2Utils.log("xxxx",errorListener == null)
            errorListener?.onParserError(errMsg(Str(lei.getConf("code")),e.message?:"",e.position))
            return null
        }
        catch (e : Exception){
            e.printStackTrace()
            errorListener?.onParserError(e.toString())
            return null
        }
    }

    /**
     * p2 一般应用于子类。 有错误则报错。
     */
    fun p2(j2: J2Node, lei: JianLeiApi) : Any{
        try {
            return p(j2,lei)
        }catch (e : TokenException){
            e.printStackTrace()
            lei.getParserListener()?.onLangError(errMsg(Str(lei.getConf("code")),e.message?:"",e.position))

            return "失败a ${e}"
        }catch (e : ParserException){
            e.printStackTrace()
            J2Utils.log("失败了",lei.getConf("parser_listener") is OnJianParserListener,lei.getConf("parser_listener")?.javaClass)
            lei.getParserListener()?.onParserError(errMsg(Str(lei.getConf("code")),e.message?:"",e.position))

            return "失败b ${e}"
        }
        catch (e : Exception){
            e.printStackTrace()
            lei.getParserListener()?.onParserError(e.toString())
            return "失败c${e}"
        }
    }

    fun errMsg(code : String,msg : String,position : Int) : String{
        val errmsg = StringBuilder(msg)
        errmsg.append("；  ")

        var h = 0
        var l = 0
        if (position > code.length) return msg
        code.substring(0,position).split("\n").let {
            h = it.size
            l = it[it.size - 1].length
        }


        // 代码编辑页，索引从1开始。没有第零行啊
        errmsg.append("位置:").append(h).append(" - ").append(l).append(" ；  ")

        val ls = code.split("\n")

        if (ls.size > 0) errmsg.append(ls[h-1])
        return errmsg.toString()
    }


    /**
     * 执行stat
     */
    fun p(j2: J2Node, data : JianLeiApi) : Any{
        var end : Any? = null

        // 抽出功能、事件、引用
        if (data !is JianLei2){
            var i = 0
            while (i < j2.nodes.size){
                j2.nodes[i].let {
                    when(it.nodeType()){
                        ENode.nfun -> {
                            data.addFun(it as NFunNode)
                            j2.nodes.removeAt(i)
                        }

                        ENode.nevent->{
                            // 变量的事件让在执行中添加到子对象中。
                            (it as NEventNode).let {
                                if (it.target == null){
                                    data.addListener(it.name,it.par2J2()!!)
                                    j2.nodes.removeAt(i)
                                }else{
                                    i++
                                }
                            }

                        }

                        // 否则正常执行
                        else -> i++
                    }
                }
            }
        }

        try {
            j2.nodes.forEach {
                end = pNode(it,data)
            }
        }
        catch (e : ReturnException){
            end =  e.returnContent
        }

        return end ?: NULL()

    }


    // **************************************************
    // ******* 简 ***********

    fun pNode(node : Node, data: JianLeiApi) : Any{
        return when(node.nodeType()){
            ENode.nvar -> data.createVar((node as NVarNode).name, pNode2(node.value,data))
            // 压根就执行不到这个
            ENode.nevent -> {

                (node as NEventNode).let {
                    if (it.target!=null){
                        val target = pNode(it.target!!,data)
                        when(target){
                            is JianLeiApi -> target.addListener(it.name,it.par2J2()!!)
                            is JianObject -> target.addListener(it.name,it.par2J2()!!,data)
                        }
                    }
                    // 理论上再 p() 函数中就吃了顶级事件
                    else{
                        data.addListener(it.name,it.par2J2()!!)
                    }
                }

            }
            ENode.nfun -> data.addFun(node as NFunNode)
            ENode.nwhen -> pWhen(node as WhenNode,data)

            // nimport,nin,
            ENode.nif -> pIf(node as IFNode,data)
            ENode.nfor -> pFor(node as ForNode,data)
            ENode.gfun -> runFun(data,node as GFunNode,data)
            ENode.obj1 -> pObj1(node as Obj1Node,data)
            ENode.obj2 -> pObj2(node as Obj2Node,data)
            ENode.suan -> pSuan(node as SuanNode,data)

            ENode.fuzhi -> {
                (node as FuzhiNode).let { fuzhi->
                    //  a[b] = right
                    if (fuzhi.left!!.nodeType() == ENode.obj1){
                        (fuzhi.left as Obj1Node).let { obj1->
                            val l = pNode(obj1.left,data)
                            val r = pNode(obj1.right,data)

                            val value =pNode(fuzhi.right!!,data)

                            // 只有数据可以这样刷
                            if (l is ARR){
                                if (r !is Number) throw ParserException.node("对象不匹配，需要整数，而你输入 ${obj1.left}[${r.javaClass.name}]",node)
                                r.toInt().let { position->
                                    if (position >=0 && position <= l.size){
                                        l.set(position,value)
                                    }else{
                                        l.add(value)
                                    }
                                }
                            }

                            // 需要字符串
                            else if (l is EON){
                                l[r.toString()] = value
                            }

                            else{
                                throw ParserException.node("对象并非数组或表项(键对值/数据) ${obj1.left} ，你的对象 ${l.javaClass.name}",node)
                            }
                        }
                    }

                    // 其他
                    else{
                        pObjVarName(fuzhi.left!!,data){parent, varName ->
                            pNode(fuzhi.right!!,data).let { value->
                                var p = true
                                if (fuzhi.symbol.length == 2){
                                    if (parent is JianLeiApi){
                                        val l = parent.getVar(varName) ?: ParserException.node("取变量 ${varName} 失败",fuzhi)
                                        // 数学运算
                                        if (l is Number && value is Number){
                                            parent.setVar(varName,when(fuzhi.symbol.substring(0,1)){
                                                "+" -> plus(l,value)
                                                "-" -> minus(l,value)
                                                "*" -> times(l,value)
                                                "/" -> div(l,value)
                                                "%" -> rem(l,value)
                                                else -> throw ParserException.node("不懂不懂不懂 你代码肯定错了",node)
                                            })
                                        }
                                    }


                                    else {
                                        p = false
                                    }
                                }else{
                                    try {
                                        if (parent is JianLeiApi) {
                                            parent.setVar(varName,value)
                                        }
                                        else if (parent is JianObject){
                                            parent.setPar(varName,value)
                                        }
                                        else {
                                            p = false
                                        }
                                    }catch (e: ParserException){
                                        e.position = fuzhi.position
                                        throw e
                                    }

                                }

                                if (!p) throw ParserException.node("该对象无法赋值 【 3135 ${parent.javaClass.name} 】",fuzhi)

                            }
                        }
                    }
                }

                return true
            }
            ENode.varself -> pVarSelf(node as VARSELF,data)
            ENode.ifx ->  pIfx(node as IFX,data)
            ENode.ifxIS -> pIfxIS(node as IFXIS,data)
            ENode.ifxOR -> pIfxOR(node as IFXOR,data)

            // 变量
            ENode.gvar -> {
                data.getVar((node as VarNode).name) ?: throw ParserException.node("找不到变量 ${node.name}",node)
            }


            // 返回
            ENode.RETURN -> throw ReturnException(pNode2( (node as ReturnNode).node,data))

            // 保持使用 token 的几个小函数  break、continue  即 跳出循环 跳过循环
            ENode.BREAK -> throw BreakException()
            ENode.CONTINUE -> throw BreakException()

            // 子类
            ENode.j2->{
                p(node as J2Node, JianLei2(data))
            }

            // 注释 换行符无视
            ENode.pn, ENode.notes -> ""

            ENode.c_js -> {
                return JsFactory("",data,"")
                    .p((node as JsNode).value)
            }

            ENode.c_jian -> {
                (node as E3Node).let {
                    return p(it.value,JianLei2(data))
                }
            }

            ENode.c_ex -> {

            }

            ENode.c_layout -> {
                return pLayout(NodeFactory().startLayout((node as LayoutNode).code,node.position),data)
            }



            // 节点转ARR对象
            ENode.arr -> {
                val arr = ARR()
                (node as ARRNode).datas.forEach {
                    arr.add(pNode(it,data))
                }
                return arr
            }
            ENode.eon -> {
                val eon = EON()
                (node as EONNode).datas.forEach {
                    eon.put(it.key, pNode(it.value!!,data))
                }
                return eon
            }

            ENode.boolean -> return (node as BooleanNode).value
            ENode.str -> return (node as StrNode).value
            ENode.num -> return (node as NumNode).value
            ENode.layout -> return pLayout(node as LAYOUT,data)
            ENode.nin -> return "" // 继承 暂时无效
            ENode.nimport -> {
                (node as IMPORT).let {  data.addImport(it.name,it.path) }
            }
            else -> {

                J2Utils.log("无效操作",node.nodeType(),node.javaClass)
                throw ParserException.node("解析错误",node)
            }
        }


    }

    private fun pLayout(layout : LAYOUT,data: JianLeiApi): JianViewObject {
        runFun(data,data,layout.key,ArrayList(),layout.position).let {
            if (it !is JianViewObject) throw ParserException.node("非视图对象 ${layout.key} 为 ${it.javaClass.name}",layout)

            // 搞参数
            layout.pars.forEach {p->
                it.setPar(p.key, pNode(p.value as Node,data))
            }

            // 子view
            layout.child.forEach {l->
                it.添加视图(pLayout(l,data))
            }

            return it
        }
    }

    private fun pLayout2Edit(layout : LAYOUT,data: JianLeiApi): JianViewObject {

        runFun(data,data,layout.key,ArrayList(),layout.position).let {
            if (it !is JianViewObject) throw ParserException.node("非视图对象 ${layout.key} 为 ${it.javaClass.name}",layout)
            // 搞参数
            layout.pars.forEach {p->
                pNode(p.value as Node,data).let { v->
                    it.ev.attrs[p.key] =v
                    it.setPar(p.key, v)
                }

            }

            // 子view
            layout.child.forEach {l->
                it.添加视图(pLayout2Edit(l,data))
            }

            return it
        }
    }

    // 仅多个判空
    fun pNode2(node: Node?, data: JianLeiApi, def : Any = false) : Any{
        if (node ==null ) return def
        else return pNode(node,data)
    }

    /**
     * 处理 判断
     * @param data 运行此when的主类即可。本函数内部执行时会自动创建子类
     */
    private fun pWhen(nwhen : WhenNode, data: JianLeiApi) : Any{
        try {
            if (nwhen.ifxs.size == 0) return false

            // 默认值
            val def = pNode(nwhen.ifxs[0],data)

            // 这里才匹配
            for (i in 0 until nwhen.ifxs.size - 1){

                // +1 因第一个为 def
                val eq = pNode(nwhen.ifxs[i+1],data)
                if (def == eq){
                    return p(nwhen.stats[i], JianLei2(data))
                }
            }

            // 否则
            if (nwhen.ifxs.size == nwhen.stats.size){
                return p(nwhen.stats[nwhen.stats.size - 1], JianLei2(data))
            }
        }catch (e : BreakException){
            // 跳出
        }


        // 无否则，也没有匹配成功，返回false
        return false
    }

    /**
     * 处理 if
     */
    private fun pIf(nif : IFNode, data: JianLeiApi) : Any{
        for (i in 0 until nif.ifxs.size){
            // 条件成立，执行并返回
            if (pNode(nif.ifxs[i],data) == true)
                return p(nif.stats[i], data) // if 执行下的不需要在子类（类似与js中的var。当然缺点也是很明显的！）
        }

        // 指令比判断条件多  含否则
        if (nif.stats.size-1 == nif.ifxs.size){
            return p(nif.stats[nif.stats.size-1], data)
        }

        // 无否则，也没有匹配成功，返回false
        return false
    }

    /**
     * 处理 for
     * @param data 运行此when的主类即可。本函数内部执行时会自动创建子类
     */
    private fun pFor(nfor : ForNode, data: JianLeiApi) : Any{

        try {
            // 循环条件不成立
            if (nfor.left == null || nfor.stat == null) return false

            val left = pNode(nfor.left!!,data)

            // 独自循环
            if (nfor.right == null){
                // 只有数组才可以独自循环
                if (left is ARRNode){
                    for (i in 0 until left.datas.size){
                        p(nfor.stat!!, JianLei2(data,nfor.stat!!,left.datas[i],i))
                    }
                }
                else if (left is ARR){
                    for (i in 0 until left.size){
                        p(nfor.stat!!, JianLei2(data,nfor.stat!!,left[i],i))
                    }
                }
                else if (left is Int){
                    for (i in 0 until left){
                        p(nfor.stat!!, JianLei2(data,nfor.stat!!,i))
                    }
                }
                else{
                    throw ParserException.node("循环条件需为数组 如 循环([1,2,3]){it:} 而不是 循环(${left.javaClass})",nfor)
                }
            }

            // for(a .. b){it-> }
            else {
                val right = pNode(nfor.right!!,data)

                if (left !is Int && right !is Int)
                    throw ParserException.node("循环条件需为整数  如：循环(1 .. 5){it:}",nfor)

                // untion
                if (nfor.dao){
                    for (i in (left as Int) until (right as Int)){
                        p(nfor.stat!!, JianLei2(data,nfor.stat!!,i))
                    }
                }else{
                    for (i in (left as Int) .. (right as Int)){
                        JianLei2(data,nfor.stat!!,i).let {
                            p(nfor.stat!!,it)
                        }

                    }
                }

            }
        }catch (e : BreakException){
            // 跳出
        }

        // 循环 无返回值
        return true
    }

    /**
     * 运算
     */
    private fun pSuan(suan : SuanNode, data: JianLeiApi) : Any{
        val left = pNode(suan.left!!,data)
        val right = pNode(suan.right!!,data)

        // 数学运算
        return if (left is Number && right is Number){
            when(suan.ysf){
                "+" -> return plus(left,right)
                "-" -> return minus(left,right)
                "*" -> return times(left,right)
                "/" -> return div(left,right)
                "%" -> return rem(left,right)
                else -> {
                    throw ParserException.node("这是什么运算符号？ ${suan.ysf} ",suan)
                }
            }
        }


        // 不是数学运算那就都换成字符串
        else{
            when(suan.ysf){
                "+" -> left.toString() + right.toString()
                else -> {
                    throw ParserException.node("运算类型有误，请确保运算值为数字 ${suan.left}(${left.javaClass}) " +
                            "${suan.ysf} ${suan.right}(${right.javaClass})",suan)
                }
            }
        }

    }

    /**
     * 自增、自减  i++  i--
     */
    private fun pVarSelf(n: VARSELF, data: JianLeiApi): Any {

        var r : Any ?= null
        pObjVarName(n.target!!,data){parent, varName ->
            val v = data.getVar(varName)
            if (v !is Number) throw ParserException.node("请确保自增/自减变量为整数类型",n)

            val c = v as Number

            r = when(n.mode){
                //i++  返回自增前的
                0-> {
                    data.setVar(varName, plus(c,1))
                    c
                }

                // i--
                1->{
                    data.setVar(varName, minus(c,1))
                    c
                }

                // ++i 返回自增后的
                2->{
                    plus(c,1).let {
                        data.setVar(varName, it)
                        it
                    }
                }

                // --i
                else -> {
                    minus(c,1).let {
                        data.setVar(varName, it)
                        it
                    }
                }
            }
        }

        return r!!
    }


    /**
     * 解对象取变量名，回调形式出来  obj.obj  或 obj
     */
    private fun pObjVarName(obj : Node, data: JianLeiApi, callback : (parent : Any, varName :String) ->Unit){
        when(obj.nodeType()){
            ENode.gvar -> callback(data,(obj as VarNode).name)

            // obj2.obj
            ENode.obj2 -> {
                (obj as Obj2Node).let { obj2->
                    val left = pNode(obj2.left,data)


                    // 为变量，任务完成
                    if (obj2.right.nodeType() == ENode.gvar) {
                        callback.invoke(left,(obj2.right as VarNode).name)
                    }
                    // 非变量，进一步处理
                    else {
                        throw ParserException.node("赋值对象有误 【 3125 ${obj2.right.nodeType()} 】",obj)
                        // pObjVarName(it.right,data,parent,callback)
                    }
                    return
                }
            }


            else -> throw ParserException.node("语法无效 ${obj.nodeType()}",obj)
        }
    }

    /**
     * obj1[suan]
     */
    private fun pObj1(obj1 : Obj1Node, data: JianLeiApi) : Any{
        val left = pNode(obj1.left,data)
        val right = pNode(obj1.right,data)
        when(left){
            // 数组，right 就必须为数字
            is ARR -> {
                if (right is Int) {
                    try {
                        return left[right]
                    }catch (e : IndexOutOfBoundsException){
                        throw ParserException.node("超出成员数，欲取位置${right} 数组长度${left.size}",obj1)
                    }
                }
            }
            is EON -> {
                try {
                    return left[right.toString()]!!
                }catch (e : Exception){
                    return NULL() // 不返回空
                    // throw ParserException.node("取成员 ${right} 失败",obj1)
                }
            }

            else -> {
                throw ParserException.node("这种取法只可以取数组 如 [1,2,3][0]  == 1。" +
                        "但你对象是 ${obj1.left.nodeType()}(${left.javaClass})[${obj1.right.nodeType()}(${right.javaClass})]",obj1)
            }
        }
        throw ParserException.node("这种取法只可以取数组 如 [1,2,3][0]  == 1",obj1)
    }
    private fun pObj2(obj2 : Obj2Node, data: JianLeiApi) : Any{
        try {
            return pObj2_next(pNode(obj2.left,data),obj2.right,data)
        }catch (e : Exception){
            e.printStackTrace()
            throw ParserException.node((e.message?:"取对象失败") + "",obj2)
        }

    }

    /**
     * left 需解析到的项目
     */
    private fun pObj2_next(left : Any,right : Node,data: JianLeiApi) : Any{
        when(right.nodeType()){
            ENode.gfun -> runFun(left,(right as GFunNode),data)
            ENode.gvar -> getVar(left,(right as VarNode).name,data)

            // 拆解，先取父
            ENode.obj2 -> pObj2_next(pObj2_next(left,(right as Obj2Node).left,data), right.right,data)

            else -> {
                J2Utils.log("pObj2 未知类型",right.nodeType())
                null
            }
        }.let{
            if (it == null) throw NullPointerException()
            else return it
        }

    }

    /**
     * 判断  ifx  返回 ture or false
     */
    private fun pIfx(n : IFX, data: JianLeiApi) : Boolean{

        pNode(n.left?:return false,data).let { l->

            // !left  ， 无其他操作
            if (n.right == null) {
                (if (l is Boolean) l else l !is NULL).let {
                    return if (n.ysf == "!") !it else it
                }
            }

            pNode(n.right!!,data).let { r->
                when(n.ysf){
                    "!=","!==" -> return l != r
                    "==" -> return l == r

                    // 剩下的  > < >= <=  都是数学匹配
                    else ->{

                        // 数值就比对数值，不是数值就文本比对文字长度
                        return if (l is Number && r is Number){
                            when(n.ysf){
                                ">=" -> l.toDouble() >= r.toDouble()
                                ">" -> l.toDouble() > r.toDouble()
                                "<=" -> l.toDouble() <= r.toDouble()
                                "<" -> l.toDouble() < r.toDouble()
                                else -> {
                                    J2Utils.log("ifx 未知关键词 ${n.ysf}")
                                    false
                                }
                            }
                        }else{
                            val l1 = l.toString().length
                            val r1 = r.toString().length
                            when(n.ysf){
                                ">=" -> l1 >= r1
                                ">" -> l1 > r1
                                "<=" -> l1 <= r1
                                "<" -> l1 < r1
                                else -> {
                                    J2Utils.log("ifx 未知关键词x ${n.ysf}")
                                    false
                                }
                            }
                        }

                        //if (l !is Number || r !is Number) throw ParserException.node("确保比对值均为数值，否则怎么匹配呢",n)

                    }

                }
            }


        }
    }
    private fun pIfxIS(n : IFXIS, data: JianLeiApi) : Boolean{
        pNode(n.left,data).let { l->
            pNode(n.right,data).let { r->
                // 判断类型是否一致
                (l.javaClass.name == r.javaClass.name).let {
                    return if (n.IS) it else !it
                }
            }
        }
    }

    private fun pIfxOR(n : IFXOR, data: JianLeiApi) : Boolean{

        if (n.OR){
            pNode(n.left,data).let { l->
                if (True(l)) return true
                pNode(n.right,data).let { r->
                    return True(r)
                }
            }
        }else{
            pNode(n.left,data).let { l->
                if ( !True(l)) return false
                pNode(n.right,data).let { r->
                    return True(r)
                }
            }
        }

    }


    // 并不会自增
    private fun nextToken(tokens : List<Token>,pos : Int) : Token?{
        return if (pos < tokens.size)  tokens[pos]
        else null
    }

    // ********************************************************
    // *********** 基础参数二改 ********************************

    fun toInt(t2: Any?): Int {
        return when(t2){
            is NumNode -> toInt(t2.value)
            is StrNode -> toInt(t2.value)
            is String -> {
                if (t2.contains(".")){
                    toDouble(t2).toInt()
                }else{
                    try {
                        t2.toInt()
                    }catch (e : Exception){
                        0
                    }
                }

            }
            is Double -> t2.toInt()
            is Float -> t2.toInt()
            is Int -> t2
            else -> 0
        }

    }
    fun toDouble(any : Any?) : Double{
        if (any is String){
            val sp = any.split(".")
            if (sp.size == 1) return any.toDouble()
            if (sp.size >= 2){
                try {
                    return (sp[0] + "." + sp[1]).toDouble()
                }catch (e : Exception){

                }
            }
        }else if (any is Int){
            return any.toDouble()
        }
        else if (any is Float){
            return any.toDouble()
        }
        else if (any is Double){
            return any
        }

        return 0.0
    }
    fun toNode(any: Any):Node{
        return when(any){
            is Node -> return any
            is Number -> NumNode(any)
            is String -> StrNode(any)
            is Boolean -> BooleanNode(any)
            is EON -> return EONNode(any)
            is ARR ->{
                ARRNode().let { e->
                    any.forEach {
                        e.put(toNode(it))
                    }
                    e
                }
            }
            else -> StrNode(any.toString())
        }


    }
    /**
     * string 不为空，int 不等于0 其他不为空 即可true
     */
    fun True(v : Any?) : Boolean{
        when(v){
            is Number -> return v.toString() != "0"
            is String -> return v.length > 0
            is Boolean -> return v
            else -> return v != null
        }
    }

    /**
     * 为字符串返回字符串，为数字也返回字符串，逻辑型返回空
     */
    fun Str(v : Any?) : String{
        return when(v){
            is String -> v
            is Number -> v.toString()
            is E3Node -> v.value
            is JsNode -> v.value
            is E2Node -> v.value
            is Node -> v.toString()
            else -> ""
        }
    }

    /**
     * 获取实际值
     */
    fun Value(t : Any) : String{
        if (t is Number || t is Boolean) return t.toString()
        else if (t is String) return  t
        else if (t is StrNode) return t.value
        else if (t is NumNode) return t.value.toString()
        else if (t is E3Node) return t.value
        else if (t is JsNode) return t.value
        else if (t is E2Node) return t.value
        else if (t is LayoutNode) return t.code
        else return t.toString()
    }


    /**
     * 加减乘除  + - * / %
     */
    private fun plus(a : Number,b : Number) : Number{
        when(a){
            is Int -> return a.toInt() + b.toInt()
            is Long -> return a.toLong() + b.toLong()
            is Float -> return a.toFloat() + b.toFloat()
            is Double -> return a.toDouble() + b.toDouble()
        }
        return a.toDouble() + b.toDouble()
    }
    private fun minus(a : Number,b : Number) : Number{
        when(a){
            is Int -> return a.toInt() - b.toInt()
            is Long -> return a.toLong() - b.toLong()
            is Float -> return a.toFloat() - b.toFloat()
            is Double -> return a.toDouble() - b.toDouble()
        }
        return a.toDouble() - b.toDouble()
    }
    private fun times(a : Number,b : Number) : Number{
        when(a){
            is Int -> return a.toInt() * b.toInt()
            is Long -> return a.toLong() * b.toLong()
            is Float -> return a.toFloat() * b.toFloat()
            is Double -> return a.toDouble()* b.toDouble()
        }
        return a.toDouble() * b.toDouble()
    }
    private fun div(a : Number,b : Number) : Number{
        when(a){
            is Int -> a.toDouble() / b.toInt()
            is Long -> a.toDouble() / b.toLong()
            is Float -> a.toDouble() / b.toFloat()
            is Double -> a.toDouble()/ b.toDouble()
            else -> a.toDouble() / b.toDouble()
        }.let {
            if (it.toString().endsWith(".0")) return it.toLong() else return it
        }

    }
    private fun rem(a : Number,b : Number) : Number{
        when(a){
            is Int -> return a.toInt() % b.toInt()
            is Long -> return a.toLong() % b.toLong()
            is Float -> return a.toFloat() % b.toFloat()
            is Double -> return a.toDouble()% b.toDouble()
        }
        return a.toDouble() % b.toDouble()
    }


    // ********************************************************
    // *********** 功能项 ********************************

    /**
     * 执行功能。 优先匹配用户定义的。若未找到用户定义的类就执行系统类
     */
    fun runFun(target : Any, f : GFunNode, data : JianLeiApi) : Any{ // 先运算出参数值
        val pars = ArrayList<Any>()

        // 解析参数。 键对值 输入的为 EON 转换为键对值表
        if (pars.size >= 1 && f.pars[0] is EONJNode){
            val eon = EON()
            f.pars.forEach {
                if (it is EONJNode) {
                    eon.put(it.name,it.value!!)
                }
            }
            pars.add(eon)
        }
        else{
            for (par in f.pars) {
                // stat 为听众
                if (par.nodeType() == ENode.j2) pars.add(par)
                else pars.add(pNode2(par,data))
            }
        }

        // 向目标执行功能

        return runFun(target,data,f.name,pars,f.position)

    }

    /**
     * @param position 指令位置
     */
    @Suppress("NewApi")
    private fun runFun(target : Any, data : JianLeiApi, name : String, pars : List<Any>,position : Int) : Any{
        when(target){
            is JianLeiApi -> {
                // 用户自定义的
                target.getFun(name,pars)?.let { nf->
                    // 参数列表
                    val datas = EON()

                    // 参数
                    for (i in 0 until nf.pars.size){
                        datas.put(nf.pars[i].name,pars[i])
                    }

                    return p(nf.j2?:return NULL(), JianLei2(target,datas))
                }

                // 尝试系统级
                try {
                    target.pJianSystemFun(name,*pars.toTypedArray())?.let { return it }
                }catch (e : ParserException){
                    e.position = position
                    throw e
                }

            }

            is JianObject -> {
                target.pFun(data,name,pars)?.let { return it }
            }

            // 其他的  尝试内置函数是否有匹配。 将第一参数改为 left 即可
            else -> {
                ArrayList<Any>().let {
                    it.add(target)
                    it.addAll(pars)

                    def().pFun(data,name,it)?.let { return it }
                }
            }
        }

        // 其他 系统级
        when(name){
            "输出"->{
                if (pars.isNotEmpty()){
                    StringBuilder().apply {
                        pars.forEach {
                            append(it).append("，")
                        }
                        deleteCharAt(length - 1) // 去除最后的逗号
                        data.getParserListener()?.log(toString())
                    }
                }
                return true
            }
            "数据类型"->{
                return target.javaClass.name
            }
            "到文本" -> {
                if (pars.isEmpty()) return target.toString()
                else if (target is JianLeiApi && pars.size == 1) return Str(pars[0])
            }
            "到整数" -> {
                if (pars.isEmpty()) return toInt(target)
                else if (target is JianLeiApi && pars.size == 1) return toInt(pars[0])
            }
            "到小数" -> {
                if (pars.isEmpty()) return toDouble(target)
                else if (target is JianLeiApi && pars.size == 1) return toDouble(pars[0])
            }
        }

        //throw ParserException((e.message?:"执行功能失败"),position)

        if (data == target){
            StringBuilder("${name}(").let {
                for (i in 0 until pars.size){
                    it.append("p${i}").append(":").append(pars[0].javaClass.name).append(",")
                }
                if (pars.size > 0) it.deleteCharAt(it.length - 1)
                it.append(")")
                throw ParserException("未定义功能 ${it}",position)
            }
        }

        else if (target is NULL){
            throw ParserException("未知对象 ",position)
        }

        else{

            // 尝试原生函数
            J2Utils.parserFun(target,name, pars)?.let { return it }

            // 不行 报错
            StringBuilder("${name}(").let {
                for (i in 0 until pars.size){
                    it.append("p${i}").append(":").append(pars[0].javaClass.name).append(",")
                }
                if (pars.size > 0) it.deleteCharAt(it.length - 1)
                it.append(")")
                throw ParserException("未定义功能 ${target.javaClass}.${it}",0)
            }
        }

        
    }

    /**
     * 获取变量
     */
    fun getVar(target: Any,varName : String,data: JianLeiApi) : Any{

        return when(target){
            is JianLeiApi -> target.getVar(varName)
            is JianObject -> target.getPar(varName,data)
            else -> null
        } ?: throw ParserException("未定义变量 ${varName}  【${target.javaClass}】",0)
    }



    // ********************************************************
    // *********** 其他 ********************************
    fun isEmpty(n : Any?) : Boolean{
        return when (n) {
            null -> true
            is String -> n.isEmpty()
            is Int -> n == 0
            is Float -> n == 0F
            is Boolean -> n == false
            else -> false
        }
    }
    fun name2obj(name : String) : Node{
        return when(name){
            "赋值","变量赋值" -> FuzhiNode(VarNode("对象",0),"=",StrNode("值"))
            "创建变量" -> NVarNode()
            "创建功能" -> NFunNode()
            "执行功能" -> GFunNode()
            "引用变量" -> VarNode("",0)
            "运算","自由组合" -> ENodes()
            "循环" -> ForNode(NumNode(0),NumNode(10))
            "如果真" -> IFNode()
            "判断" -> WhenNode()
            "参数" -> ParNode()
            "文本" -> StrNode("")
            "布局" -> LayoutNode()
            "继承" -> InNode()
            "逻辑" -> BooleanNode(true)
            "引用","引用类" -> IMPORT()
            "事件","执行事件" -> NEventNode()
            "符号" -> SymbolNode("+")
            "注释" -> NotesNode("")
            "返回" -> ReturnNode()
            "跳出循环" -> BreakNode()
            "跳过" -> ContinueNode()

            else -> {
                J2Utils.log("error jian name2obj",name)
                J2Node()
            }
        }
    }
    fun isKEY(str : String) : Boolean{
        return eqRex(str,"^[\\u4e00-\\u9fa5A-Za-z_]+[\\u4e00-\\u9fa5A-Za-z0-9_]*$")
    }

    // 是否E2代码  是否符合规则
    fun isE2Code(code: String): Boolean {
        return !code.isEmpty() && Jian.def().正则比较(code,"^(\\.[a-zA-Z_][a-zA-Z0-9_]{0,4}\\(.*?\\))+\$")
    }

    /**
     * 正则匹配
     * @param text 要匹配的内容
     * @param reg 正则
     */
    fun eqRex(text: String, reg: String): Boolean {
        if (text == reg) return true
        try {
            return if (text.isEmpty() || reg.isEmpty()) false
            else {
                val matcher = Pattern
                    .compile(reg, Pattern.CASE_INSENSITIVE)
                    .matcher(text)
                return matcher.find()
            }
        }catch (ex : java.lang.Exception){
            ex.printStackTrace()
            return false
        }
    }

}